import json
from datetime import datetime
import base64
import requests
from django.utils import timezone
from rest_framework.exceptions import ValidationError
from django.conf import settings
from apps.tenant.models import ProviderTelehealth
from apps.tenant.types import ProviderTelehealthType


def verify_zoom_access_token(telehealth):
    try:
        token = telehealth.access_token
        # Split the token into its three parts: header, payload, and signature
        header, payload, signature = token.split('.')

        # Base64 decode the header and payload
        decoded_payload = base64.urlsafe_b64decode(payload + '=' * (-len(payload) % 4)).decode('utf-8')

        # Parse the JSON data in the decoded header and payload
        payload_data = json.loads(decoded_payload)
        expiration_time = payload_data.get('exp')
        if expiration_time:
            now = datetime.now().timestamp()

            if expiration_time > now:
                # Token is still valid
                return True
            else:
                # Token has expired
                return False
        else:
            return None
    except Exception as e:
        # Handle token decoding errors
        print(f"Error decoding JWT token: {str(e)}")
        return None


def get_zoom_new_access_token(telehealth):
    headers = {
        'Content-Type': 'application/x-www-form-urlencoded'
    }
    data = {
        'grant_type': 'refresh_token',
        'refresh_token': telehealth.refresh_token,
        'client_id': settings.ZOOM_CLIENT_ID,
        'client_secret': settings.ZOOM_CLIENT_SECRET
    }
    response = requests.post('https://zoom.us/oauth/token', data=data, headers=headers)
    if response.status_code == 200:
        token_data = response.json()
        telehealth.access_token = token_data['access_token']
        telehealth.refresh_token = token_data['refresh_token']
        telehealth.save()
        return telehealth.access_token
    else:
        try:
            telehealth.delete()
            raise Exception('Your zoom account is no longer connected')
            # Additional code or logging if needed
        except Exception as e:
            raise ValidationError(e)


def create_zoom_meeting(provider, start_date, start_time, end_time):
    # User access token

    telehealth = ProviderTelehealth.objects.filter(telehealth_type=ProviderTelehealthType.ZOOM.value).first()

    access_token = None

    if telehealth:
        start_datetime = timezone.make_aware((datetime.combine(start_date.date(), start_time)),
                                             timezone.get_current_timezone())
        end_datetime = timezone.make_aware((datetime.combine(start_date.date(), end_time)),
                                           timezone.get_current_timezone())
        duration = ((end_datetime - start_datetime).total_seconds()) / 60

        check = verify_zoom_access_token(telehealth)
        if check is True:
            access_token = telehealth.access_token
        elif check is False:
            access_token = get_zoom_new_access_token(telehealth)
        else:
            raise ValidationError('Something went wrong')
    else:
        raise ValidationError('You are no longer connected to Zoom')

    if access_token:
        headers = {
            'Authorization': f'Bearer {access_token}',
            'Content-Type': 'application/json'
        }
        data = {
            'topic': 'My Zoom Meeting',
            'type': 2,
            'start_time': start_datetime.isoformat(),  # Adjust with your desired start time
            'duration': duration,
        }
        response = requests.post('https://api.zoom.us/v2/users/me/meetings', headers=headers, json=data)
        meeting_data = response.json()

        # Get the meeting URL
        meeting_url = meeting_data['join_url']
        return meeting_url
    raise ValidationError('Something went wrong')


def get_google_new_access_token(telehealth):
    token_endpoint = 'https://oauth2.googleapis.com/token'

    data = {
        'client_id': settings.GOOGLE_CLIENT_ID,
        'client_secret': settings.GOOGLE_CLIENT_SECRET,
        'refresh_token': telehealth.refresh_token,
        'grant_type': 'refresh_token'
    }

    try:
        response = requests.post(token_endpoint, data=data)
        if response.status_code == 200:
            response_data = response.json()
            new_access_token = response_data['access_token']

            telehealth.access_token = new_access_token
            telehealth.save()
            return new_access_token
        else:
            try:
                telehealth.delete()
                raise Exception("Your Google account is no longer connected")
                # Additional code or logging if needed
            except Exception as e:
                raise ValidationError(e)
    except requests.exceptions.RequestException as e:
        raise ValidationError('Something went wrong with the Telehealth! Try again.')


def verify_google_access_token(telehealth):
    url = 'https://www.googleapis.com/calendar/v3/users/me/calendarList'
    access_token = telehealth.access_token
    headers = {
        'Authorization': f'Bearer {access_token}',
        'Content-Type': 'application/json',
    }
    try:
        response = requests.get(url, headers=headers)
        if response.status_code == 200:
            return telehealth.access_token  # Access token is valid and associated with a Google account
        else:
            return get_google_new_access_token(
                telehealth)  # Access token is either invalid or does not have the necessary permissions
    except requests.exceptions.RequestException as e:
        raise ValidationError('Error with the token authentication')


def create_meeting(provider, start_date, start_time, end_time):
    telehealth = ProviderTelehealth.objects.filter(telehealth_type=ProviderTelehealthType.GOOGLE_MEET.value).first()

    if telehealth:
        access_token = verify_google_access_token(telehealth)
        start_datetime = timezone.make_aware((datetime.combine(start_date.date(), start_time)),
                                             timezone.get_current_timezone())
        end_datetime = timezone.make_aware((datetime.combine(start_date.date(), end_time)),
                                           timezone.get_current_timezone())

        # Create the meeting
        try:
            event = {
                'summary': 'My Meeting',
                'start': {'dateTime': start_datetime.isoformat()},
                'end': {'dateTime': end_datetime.isoformat()},
                'conferenceData': {
                    'createRequest': {'requestId': 'random_string_or_unique_id'},
                },
            }
            # Create the Calendar client
            headers = {'Authorization': f'Bearer {access_token}'}
            url = 'https://www.googleapis.com/calendar/v3/calendars/primary/events?conferenceDataVersion=1'
            response = requests.post(url, headers=headers, data=json.dumps(event))

            if response.status_code == 200:
                created_event = response.json()
                conference_data = created_event['conferenceData']
                video_call_link = conference_data['entryPoints'][0]['uri']
                return video_call_link

            # Handle error response
            else:
                raise ValidationError('Token no longer works')
        except Exception as e:
            print(e)
            raise ValidationError('Something Went wrong')
    else:
        raise ValidationError('You are no longer connected with Google')
